/**
 * @file thread7.c
 * @brief 电机通信线程实现
 * 
 * 该线程负责通过RS232接口与电机控制器进行通信。主要功能包括：
 * 1. 初始化RS232串口接口（/dev/ttyS9，对应外部连接器COM2口）
 * 2. 向电机发送控制指令
 * 3. 接收电机状态和反馈信息
 * 4. 处理电机数据
 * 5. 在程序退出时释放串口资源
 * 
 * @note 该线程预留用于与电机控制器通信，具体协议待定
 * 
 * @author 伞控无人机项目组
 * @date 2023
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <pthread.h>
#include <stdint.h>
#include "thread7.h"
#include "uart_common.h"

// 模块名称定义（统一使用标准模块名，避免重复）
#ifndef THREAD7_MODULE
#define THREAD7_MODULE LOG_MODULE_MOTOR
#endif

// 全局变量
static int g_motor_rs232_fd = -1;  // 串口文件描述符
static int g_thread_running = 1;   // 线程运行标志

/**
 * @brief 初始化电机RS232串口
 * 
 * @param device 串口设备名
 * @param baudrate 波特率
 * @return 成功返回文件描述符，失败返回-1
 */
int motor_rs232_init(const char *device, int baudrate) {
    // 使用新的UART通用模块初始化串口
    uart_config_t config = {
        .baudrate = baudrate,
        .data_bits = 8,
        .stop_bits = 1,
        .parity = 0,
        .flow_control = 0,
        .timeout_ms = 100,
        .buffer_size = 65536,
        .flags = UART_FLAG_RAW_MODE | UART_FLAG_LARGE_BUFFER
    };
    
    int fd = uart_init_device(device, UART_TYPE_RS232, &config);
    if (fd < 0) {
        LOG_ERROR(LOG_TO_CONSOLE_ONLY, THREAD7_MODULE, "打开电机串口设备失败: %s", strerror(errno));
        return -1;
    }
    
    LOG_INFO(LOG_TO_CONSOLE_ONLY, THREAD7_MODULE, "电机串口 %s 初始化成功，波特率: %d", device, baudrate);
    return fd;
}

/**
 * @brief 向电机发送指令
 * 
 * @param fd 串口文件描述符
 * @param buffer 发送缓冲区
 * @param length 要发送的数据长度
 * @return 成功返回发送的字节数，失败返回-1
 */
int motor_send_command(int fd, const uint8_t *buffer, int length) {
    // 检查参数
    if (fd < 0 || buffer == NULL || length <= 0) {
        return -1;
    }
    
    // 发送数据
    int ret = write(fd, buffer, length);
    if (ret < 0) {
        LOG_ERROR(LOG_TO_CONSOLE_ONLY, THREAD7_MODULE, "发送电机指令错误: %s", strerror(errno));
        return -1;
    }
    
    // 等待数据发送完成
    tcdrain(fd);
    
    LOG_DEBUG(LOG_TO_CONSOLE_ONLY, THREAD7_MODULE, "向电机发送指令: %d 字节", ret);
    return ret;
}

/**
 * @brief 接收电机应答
 * 
 * @param fd 串口文件描述符
 * @param buffer 接收缓冲区
 * @param buffer_size 缓冲区大小
 * @param timeout_sec 超时秒数
 * @param timeout_usec 超时微秒数
 * @return 实际接收的数据长度，超时返回0，错误返回-1
 */
int motor_receive_response(int fd, uint8_t *buffer, int buffer_size, int timeout_sec, int timeout_usec) {
    fd_set readfds;
    struct timeval timeout;
    int ret, total_bytes = 0;
    
    // 检查参数
    if (fd < 0 || buffer == NULL || buffer_size <= 0) {
        return -1;
    }
    
    // 清空缓冲区
    memset(buffer, 0, buffer_size);
    
    // 设置超时
    timeout.tv_sec = timeout_sec;
    timeout.tv_usec = timeout_usec;
    
    // 循环读取数据，直到超时或缓冲区满
    while (total_bytes < buffer_size) {
        // 设置文件描述符集
        FD_ZERO(&readfds);
        FD_SET(fd, &readfds);
        
        // 等待数据可读或超时
        ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
        
        if (ret == -1) {
            // 发生错误
            LOG_ERROR(LOG_TO_CONSOLE_ONLY, THREAD7_MODULE, "select错误: %s", strerror(errno));
            return -1;
        } else if (ret == 0) {
            // 超时，返回已读取的字节数
            return total_bytes;
        } else {
            // 数据可读
            if (FD_ISSET(fd, &readfds)) {
                ret = read(fd, buffer + total_bytes, buffer_size - total_bytes);
                
                if (ret < 0) {
                    // 读取错误
                    LOG_ERROR(LOG_TO_CONSOLE_ONLY, THREAD7_MODULE, "读取电机应答错误: %s", strerror(errno));
                    return -1;
                } else if (ret == 0) {
                    // 没有更多数据
                    break;
                } else {
                    // 成功读取数据
                    total_bytes += ret;
                    
                    // 重置超时，确保每次读取后都有完整的超时时间
                    timeout.tv_sec = timeout_sec;
                    timeout.tv_usec = timeout_usec;
                }
            }
        }
    }
    
    LOG_DEBUG(LOG_TO_CONSOLE_ONLY, THREAD7_MODULE, "接收电机应答: %d 字节", total_bytes);
    return total_bytes;
}

/**
 * @brief 处理电机数据
 * 
 * @param rx_buffer 接收缓冲区
 * @param rx_length 接收数据长度
 * @param tx_buffer 发送缓冲区
 * @param tx_length 指向发送数据长度的指针，函数会更新此值
 */
void motor_process_data(const uint8_t *rx_buffer, int rx_length, uint8_t *tx_buffer, int *tx_length) {
    // 检查参数
    if (rx_buffer == NULL || tx_buffer == NULL || tx_length == NULL) {
        *tx_length = 0;
        return;
    }
    
    // TODO: 根据电机协议实现数据处理逻辑
    // 当前为预留函数，后续根据具体协议实现
    
    LOG_DEBUG(LOG_TO_CONSOLE_ONLY, THREAD7_MODULE, "处理电机数据: 接收 %d 字节", rx_length);
    
    // 预设发送长度为0，表示暂无需发送数据
    *tx_length = 0;
}

/**
 * @brief 关闭电机串口
 * 
 * @param fd 串口文件描述符
 */
void motor_rs232_close(int fd) {
    if (fd >= 0) {
        close(fd);
        LOG_INFO(LOG_TO_CONSOLE_ONLY, THREAD7_MODULE, "电机串口已关闭");
    }
}

/**
 * @brief 线程7主函数 - 电机通信
 * 
 * @param arg 线程参数
 * @return void* 
 */
void* thread7_function(void* arg) {
    (void)arg;  // 标记参数为未使用
    LOG_INFO(LOG_TO_FILE, LOG_MODULE_MOTOR, "线程7启动: 电机通信");

    // 初始化串口
    g_motor_rs232_fd = motor_rs232_init(MOTOR_RS232_DEVICE, MOTOR_RS232_BAUDRATE);
    if (g_motor_rs232_fd < 0) {
        LOG_ERROR(LOG_TO_FILE, LOG_MODULE_MOTOR, "初始化电机串口失败，线程7退出");
        return NULL;
    }
    
    // 线程内发送/接收缓冲区与长度变量
    uint8_t tx_buffer[MOTOR_TX_BUFFER_SIZE];
    uint8_t rx_buffer[MOTOR_RX_BUFFER_SIZE];
    int tx_length = 0;
    int rx_length = 0;

    // 主循环
    while (g_thread_running) {
        // 初始化发送缓冲区
        memset(tx_buffer, 0, MOTOR_TX_BUFFER_SIZE);
        tx_length = 0;
        
        // 处理电机数据，生成指令
        motor_process_data(NULL, 0, tx_buffer, &tx_length);
        
        // 发送指令到电机
        if (tx_length > 0) {
            if (motor_send_command(g_motor_rs232_fd, tx_buffer, tx_length) < 0) {
                LOG_ERROR(LOG_TO_FILE, LOG_MODULE_MOTOR, "发送电机指令失败");
                sleep(1);
                continue;
            }
        }
        
        // 接收电机应答，超时1秒
        rx_length = motor_receive_response(g_motor_rs232_fd, rx_buffer, MOTOR_RX_BUFFER_SIZE, 
                                     MOTOR_RS232_TIMEOUT_SEC, MOTOR_RS232_TIMEOUT_USEC);
        
        if (rx_length < 0) {
            // 接收错误
            LOG_WARN(LOG_TO_CONSOLE_ONLY, THREAD7_MODULE, "接收电机应答错误，重试...");
            sleep(1);
            continue;
        } else if (rx_length > 0) {
            // 接收到电机应答，处理数据
            LOG_DEBUG(LOG_TO_CONSOLE_ONLY, THREAD7_MODULE, "接收到电机应答: %d 字节", rx_length);
        }
        
        // 延时一小段时间，避免过于频繁的通信
        usleep(100000);  // 100ms
    }
    
    // 关闭串口
    motor_rs232_close(g_motor_rs232_fd);
    g_motor_rs232_fd = -1;
    
    LOG_INFO(LOG_TO_FILE, LOG_MODULE_MOTOR, "线程7退出");
    return NULL;
}

void thread7_stop(void) {
    LOG_INFO(LOG_TO_CONSOLE_ONLY, LOG_MODULE_MOTOR, "线程7停止中");
    // 这里可以添加停止逻辑
} 